/* api */
import * as TaskApi from '@src/api/TaskApi.ts'
import { bindCustomer } from '@src/api/ProductV2Api'
import { getRichTextContent } from '@src/api/SystemApi'
import { eventConversionTask } from '@src/api/EventApi.js'

/* component */
import TaskEditForm from '@src/modules/task/edit/components/TaskEditForm/TaskEditForm.vue'
import PlanTaskEditForm from '@src/modules/task/edit/components/PlanTaskEditForm/PlanTaskEditForm.vue'
import TaskAllotModal from '@src/modules/task/components/TaskAllotModal/TaskAllotModal.tsx'
import TaskProcessSteps from '@src/modules/task/components/TaskProcessSteps/TaskProcessSteps.tsx'
import PartSeviceList from '@src/modules/task/editAllot/components/PartSeviceList/PartSeviceList.vue'
import ProposeApproveDialog from '../components/ProposeApproveDialog.vue'
import ProposeApproveDialog2 from '@src/modules/task/view/components/ProposeApproveDialog.vue'
import FormCellChange from '@src/component/compomentV2/FormCellChange/index.vue'
/* enum */
import TaskStateEnum from '@model/enum/TaskStateEnum.ts'
/* utils */
import {parse} from '@src/util/querystring';
import * as FormUtil from '@src/component/form/util'
import * as util from '@src/modules/task/util/task'
import _ from 'lodash'
import { isEmpty } from '@src/util/type'
import platform from '@src/platform'
import { scrollIntoFirstRequireDom,  } from '@src/util/dom';
import {
  customerAddressSelectConversion,
  customerSelectConversion,
  linkmanSelectConversion
} from '@src/util/conversionFunctionUtil.ts'
import dingtalk from '@src/util/dingtalk';
/* vue */
import data from './data'
import computed from './computed'
import methods from './methods'
/* enum */
import { TaskFieldNameMappingEnum } from '@model/enum/FieldMappingEnum.ts'
import TenantDataLimitSourceEnum from '@model/enum/TenantDataLimitSourceEnum'
import TenantDataLimitTypeEnum from '@model/enum/TenantDataLimitTypeEnum'
/* mixin */
import VersionMixin from '@src/mixins/versionMixin/index.ts'
import { ConnectorModuleConnectorCreateTaskMixin } from '@src/modules/connector'
/* constant */
import {
  PLATN_TASK_PLAN_TIME_REQUIRES_MESSAGE,
  ONLY_SELECT_ONE_QUALITY,
  PLAN_START_TIME_NOT_LESS_THEN_NOW_MEESSAGE,
  PLAN_END_TIME_NOT_LESS_THEN_NOW_MEESSAGE
} from '@src/model/const/Alert.ts'
/* mixin */
import ThemeMixin from '@src/mixins/themeMixin/index.ts'
import { isCalendar } from '@src/util/CalendarUtil';
import { openAccurateTab } from '@src/util/platform'
import { PageRoutesTypeEnum } from 'pub-bbx-global/pageType/dist/enum/PageRoutesEnum'
import i18n from '@src/locales'
import { formatDate, parseDateTime, useFormTimezone } from 'pub-bbx-utils'
import { taskAddTask, insertSelectCallByAdditionalId} from '@src/api/ProjectManage.ts'
import {safeNewDate} from "@src/util/time";
const { disposeFormViewTime, disposeFormSubmitTime } = useFormTimezone()

let taskTemplate = {};
let query = parse(window.location.search) || {}

export default {
  name: 'task-edit-view',
  inject: ['initData'],
  mixins: [VersionMixin, ThemeMixin, ConnectorModuleConnectorCreateTaskMixin],
  props: {
    planStartTime: {
      type: String,
      default: ''
    },
    planEndTime: {
      type: String,
      default: ''
    },
    planTimeConfig: {
      type: Number,
      default: 30
    }
  },
  provide() {
    return {
      // 工单是否编辑
      isEdit: this.isTaskEdit
    }
  },
  data() {
    
    data.pageTitle = '';
    data.formEditingMode = ''
    data.packUp = true
    data.template = taskTemplate
    data.hasRepeatRepair = false
    data.isQualityApprove = 0
    data.approveForm = {}
    data.needAppove = false
    data.createNeedApprove = false // 新建工单是否需要审批，包括高级审批
    // 新建工单审批弹窗参数
    data.approveDialogOptions = {
      shadable: true,
      minMenu: false,
      maxMenu: false
    }
    data.taskId = ''
    data.qualityInfo = {}
    data.qualityId = 0
    data.productId = ''
    data.outFieldRule = []
    data.inFieldRule = []
    data.templateId = ''
    data.QualitySubtext = ''
    data.DialogVisible = false
    data.isCalendar = isCalendar
    data.fields = []
    data.isShowPlanStartTime = false
    data.isShowPlanEndTime = false
    data.key = 0
    data.loadingPage = false
    data.contractId = null
    data.deadlineTime = ''
    data.formCellCount = 1
    data.needServerDeleFiles = []
    data.customCardList = []
    data.cardForms = []
    data.createNeedApprove = false;
    return data
  },
  computed,
  watch: {
    currentTaskTemplateId(newVal) {
      this.fetchSparepartServiceConfig(newVal);
      this.fetchTaskCardByIds(newVal);
    },
    'form.planStartTime'() {
      let planStartTimeField = this.fields.filter(field => field.formType == 'planStartTime')[0] || {}
      if(isEmpty(planStartTimeField)) return this.isShowPlanStartTime = false
      if(!this.form?.planStartTime) return this.isShowPlanStartTime = false
      return this.isShowPlanStartTime = true
    },
    'form.planEndTime'() {
      let planEndTimeField = this.fields.filter(field => field.formType == 'planEndTime')[0] || {}
      if(isEmpty(planEndTimeField)) return this.isShowPlanEndTime = false
      if(!this.form?.planEndTime) return this.isShowPlanEndTime = false
      return this.isShowPlanEndTime = true
    },
    'form.quality.qualityStatus'(val) {
      let obj = {}
      if(val == 'OUT' || val == '保外') {
        obj = this.format(this.outFieldRule, this.inFieldRule)
      }else if(val == 'IN' || val == '保内'){
        obj = this.format(this.inFieldRule, this.outFieldRule)
      }else {
        let obj1 = this.formatData(this.inFieldRule)
        let obj2 = this.formatData(this.outFieldRule)
        obj = {...obj1, ...obj2}
      }
      Object.keys(obj).forEach(item => {
        this.form[item] = obj[item];
        let index = this.fields.findIndex(field => field.fieldName == item)
        if(index > -1) {
          this.fields[index] = !isEmpty(obj[item]) 
            ? {...this.fields[index], disabled: true, needShowToast: true } : {...this.fields[index], disabled: false, needShowToast: false }
        }
      })
    },
    // 改变模版的时候要获取新的模版id，获取字段规则
    templateId(newVal, oldVal ) {
      if(newVal !== oldVal ) {
        this.insertParams()
      }
    },
    showSparepartServiceList:{
      handler(newVal, oldVal) {
        if(newVal) {
          // 有附加组件的时候，无法多列
          this.formCellCount = 1
        }
      },
      immediate: true
    },
    customCardList: {
      handler(newVal, oldVal) {
        if(newVal?.length) {
          // 有附加组件的时候，无法多列
          this.formCellCount = 1
        }
      },
      immediate: true
    }
  },
  async mounted() {
    this.loadingPage = true
    let isShowGuide = sessionStorage.getItem('isUserGuide') ? sessionStorage.getItem('isUserGuide') : 0
    if(!!isShowGuide && this.allowCreateTask ){
      this.isOpenGuide()
    }
    try {
      await this.fetchTaskTypeList()
      this.initialize();
      // this.isCalendar =  JSON.parse(localStorage.getItem('isCalendar'))
      // 初始化默认值
      let form = this.workTask;

      // 事件子表单数据转换到工单
      if(this.isFromEvent){
        form = await this.eventConversionTaskSubForms(form)
      }

      // 合同详情页跳转进来会跳转地址上会传入合同id
      this.contractId = window.location.href.split('contractId=')[1]
      if (this.contractId){
        // 获取合同相关的客户和产品数据，用于页面回显
        const res = await TaskApi.getContractCustomerApi({contractId:this.contractId})
        if(res.success){
          this.workTask.customer = res.result?.customer || {}
          this.workTask.products = res.result?.products || []
        }

        // TODO 根据合同id获取合同生效失效时间赋值给计划开始结束时间
        // 根据合同id获取合同生效失效时间赋值给计划开始结束时间
        const result = await TaskApi.getContractTime({ contractId: this.contractId })
        if(result.success) {
          this.workTask.planStartTime = formatDate(result.result?.planStartTime, 'yyyy-MM-dd HH:mm:ss');
          this.workTask.planTime = formatDate(result.result?.planStartTime, 'yyyy-MM-dd');
          this.deadlineTime = formatDate(result.result?.planEndTime, 'yyyy-MM-dd');
        }
      }

      let customer = form.customer;

      // 钉钉crm敏感信息授权同步
      try {
        if(customer && customer.lmPhone == 0 && dingtalk.inDingTalkCrm ) {
          let lmPhone = await dingtalk.getCrmData(customer.id);
          form.customer.lmPhone = lmPhone;
          this.$platform.alert(i18n.t('task.edit.syncLinkmanSuccess'));
        }
      } catch (error) {
        console.error(`[ddtalk jsapi]:${ error}`);
        if(error) this.$platform.alert(error);
      }
      this.productId = form && form.products && form.products[0] && form.products[0].id || ''
      if (this.productId){
        let productIds = form.products.map((item) => item.id)
        // 更新产品数据，用于提交
        const res = await TaskApi.getRelatedInfos({customerId:customer.id, productIds})
        if(res.success){
          // bug23358、24370导致产品新建工单时没有带入联系人和地址
          if (this.isFromProduct) {
            this.workTask.products = (res.result?.productInfo || []).map(item => {
              // getRelatedInfos接口没有联系人、地址字段，重新取值
              const product = form.products.find(item2 => {
                return item2.id == item.id
              })
              return {
                ...item,
                address: product?.address,
                linkman: product?.linkman
              }
            })
          } else {
            this.workTask.products = res.result?.productInfo || []
          }
        }
      }

      let params = { typeId: this.genTemplateId(), tableName: 'task', isFromSetting: true, isShowRichText:true };
      if(this.isFromPlan){
        params.isShowPlanNumber = true 
      }
      let field_ = []
      if(this.isTaskAllCustomNodeFields) {
        const { result = []} = await TaskApi.getTheFieldOfNodesThatHaveBeenPassed({ taskId: this.editId })
        field_ = result?.map(item => {
          // 引用字段不能编辑
          if(item.link) {
            this.$set(item, 'disabled', true)
            this.$set(item, 'isNull', 1) // 引用字段在编辑工单的时候不校验必填
          }
          return item;
        })
      }else {
        field_ = await TaskApi.getAllFields(params);
      }
      this.loadingPage = false
      let richtextObj_ = {};
      field_.forEach(async field => {
        if (field.fieldName == 'isRepeatRepair') {
          this.hasRepeatRepair = true
        }
        if(field.formType == 'richtext'){
          // 富文本信息需要从接口获取
          let { isSystem, fieldName } = field;
          let { task : task_ } = this.initData;
          let id = isSystem == 1 ? task_[fieldName] : task_.attribute[fieldName];
          if(id){
            richtextObj_[id] = fieldName;
          }
        }
      })

      this.fields = field_;
      // 过滤不能编辑的自定义字段 不展示(是否重复报修)
      this.fields = this.fields.filter(field => field.setting?.isEdit != 0)

      if (this.isFromProject) {
        // 如果是项目管理新建任务过来的 禁用工单类型
        let taskNoField = this.fields.filter((field) => field.fieldName === 'taskNo')[0]
        taskNoField.disabled = true
      }
    
      this.handlePlantimeFields()
      
      try {
        if (form.taddress?.id && form.customer?.id) {
          // TODO:这里暂时用获取地址列表接口去拿地址详情数据，下一次迭代后端会写地址详情接口
          const addressListRes = await TaskApi.getTaskCustomerAddress({
            customerId: form.customer.id,
            pageNum: 1,
            pageSize: 99
          })
          const addressList = addressListRes.data || []
          addressList.forEach(ad => {
            if (ad.id == form.taddress.id) {
              const {address, city, dist, id, latitude, longitude, province, country} = ad
              // 更新表单的地址数据，解决编辑客户时修改了地址不能选中最新地址
              form.taddress = {address, city, dist, id, latitude, longitude, province,country}
            }
          })
        }
      } catch(error) {
        console.warn(error, 'getTaskCustomerAddress error try catch');
      }
      // 从产品详情跳转过来时给产品数据赋值customerId
      if (window.location.pathname.indexOf('/task/createFromProduct') >= 0) {
        if (form.products?.length && form.customer?.id) {
          form.products.map(product => {
            product.customerId = form.customer.id
            return product
          })
        }
      }
      form = util.packToForm(this.fields, disposeFormViewTime(this.fields, form)); // 处理表单时间数据
      this.form = FormUtil.initialize(this.fields, form);


      // 工单任务暂存或者新增的时候，走连接器匹配规则
      if (this.isFromProject && (this.isProjectTaskDraft || this.isProjectTaskAdd)) {
          await this.projectToTaskForm()
      }

      let richtextIds = Object.keys(richtextObj_) || [];
      if (richtextIds.length) {
        let content_ = await getRichTextContent({
          ids: richtextIds,
        });
        let richtextCon = '';
        if (content_.code == 0) {
          content_.result.forEach((item, index) => {
            let key_ = richtextIds[index];
            let fieldName_ = richtextObj_[key_];
            try {
              richtextCon = item.content;
            } catch (error) {
              console.warn(error, 'error try catch');
            }
            console.log(this.form, fieldName_, 'fieldName_')
            this.form[fieldName_] = richtextCon;
          });
        }
      }
      this.form.templateId = this.genTemplateId();
      if(this.planStartTime && this.planEndTime) {
        ++this.key
        this.form.planStartTime = this.planStartTime
        this.form.planEndTime = this.planEndTime
      }
      this.insertParams()
      // 呼叫中心需求处理
      this.callCenterWithTaskDataHandler();
      
      this.init = true;
      
      this.$nextTick(() => {
        // 从客户新建工单处理
        this.customerCreateTaskHandler();
        // 从产品新建工单处理
        this.productCreateTaskHandler();
      })
      // 关联项查询处理
      this.relationFieldHandler();
      this.getQualityInfo()
      // 是否打开派单设置弹窗
      this.$nextTick(async () => {
        
        if(query.openAllotSetting) {
          await this.planTaskEditDialogOpen();
        }
      })
      
      // 版本数量限制
      this.checkNumExceedLimitHandler()
      
      if(this.task?.id) {
        this.fetchTaskCardByIds(this.task.id);
      }
      
      // 获取连接器数据
      // this.fetchConnectorInsertSelectCall()
      
    } catch (error) {
      console.warn('error ', error)
    }
  },
  beforeDestroy() {
    this.removeConnectorCreateSessionData()
  },
  methods: {
    ...methods,
    updateCreateApprove(val = false) {
      this.createNeedApprove = val
    },
    async fetchTaskTypeList() {
      try {
        const { succ = true, status, data  } = await TaskApi.getCurrentAllTaskTypeList()
        if(succ) {
          this.taskTypeObj = data
        }
      } catch(e) {
          console.error('【fetch TaskApi.getCurrentAllTaskTypeList error】', e)
      }
    },

    // 工单任务类型连接器规则字段匹配赋值
    async projectToTaskForm() {
      const { projectId, additionalId } = this.$route.query

      if (!additionalId) return 
      let params = {
        fromBizId: projectId,
        additionalId: additionalId || '',
        // 以下字段后端要求固定写死
        useScene: 'PROJECT_TASK_RULE',
        toBizType: 'TASK',
        fromBizType: 'PROJECT_MANAGER',
      }
      await insertSelectCallByAdditionalId(params).then(async (res) => {
        if (!res.success) return this.$message.error(res.message)


        // 客户信息
        const customer = res?.data?.customer || {}
        // 客户地址
        const customerAddress = customer?.customerAddress || {}
        // 客户联系人
        const customerLinkman = customer?.linkman || {}


        let resultObj = {
          ...res?.data,
          ...res?.data?.attribute,
          // 客户地址和客户联系人字段转换
          taddress: customerAddress,
          tlmId: customerLinkman?.id || '',
          tlmName: customerLinkman?.name || '',
          tlmPhone: customerLinkman?.phone || '',
        }

        let defaultform = util.packToForm(this.fields, disposeFormViewTime(this.fields, resultObj)); // 处理表单时间数据
        let newValue = (FormUtil.initialize(this.fields, defaultform));
        

        Object.keys(newValue).forEach(key => {
          const value = newValue[key]
          this.$set(this.form, key, value)
        })
        this.$refs?.form?.rerenderFormBuilder()
      })
    },
    isOpenGuide(){
      this.$Guide([{
        content: i18n.t('task.guide.editTip1'),
        fixedStep: true,
        nowStep: 3,
        totalStep:5,
        arrowOutsideStyle:{
          left:'20px'
        },
        id: 'task-edit-view-copy',
        domId: 'task-edit-view',
        domObj:()=>{
          return document.getElementById('task-edit-view-copy')
        },
        needCover: false,
        finishBtn: i18n.t('common.base.nextStep'),
      }], 0, '', (e) => {
        return new Promise((resolve, reject) => {
          if(e.type == 'finish') {
            this.submit(true)
          }else{
            resolve()
            sessionStorage.removeItem('isUserGuide')
          }
        })
      }).create().then(res_=>{if(res_)storageSet(PRODUCT_PRODUCT_LIST, '1')})
    },
    insertParams() {
      this.qualityField = this.fields.filter(field => field.formType == 'quality')[0] || {}
      this.inFieldRule = this.qualityField?.setting?.inFieldRule || []
      this.outFieldRule = this.qualityField?.setting?.outFieldRule || []
    },
    changeTemplateId(templateId) {
      this.templateId = templateId
    },
    format(fieldRule1, fieldRule2) {
      let obj1 = this.formatRule(fieldRule1)
      let obj2 = this.formatData(fieldRule2)
      return {...obj2, ...obj1}
    },
    formatRule(fieldRule) {
      let obj = {}
      fieldRule.forEach(item => {
        obj[item.fieldName] = item.fieldValue
      });
      return obj
    },
    formatData(fieldRule) {
      let obj = {}
      fieldRule.forEach(item => {
        obj[item.fieldName] = ''
      });
      return obj
    },
    getQualityInfo() {
      if(this.isTaskEdit || this.workTask.isDelete == 5) {
        TaskApi.getQualityByTaskId({ taskId: this.task.id }).then(res => {
          this.isQualityApprove = res.result.inApprove
          this.$set(this.form, 'quality', res.result)
          // 产品更新质保用于提交
          if (this.form.product && this.form.product[0]) {
            const {qualityStartTime, qualityEndTime, qualityStatus} = this.form.product[0]
            this.$set(this.form.quality, 'qualityStartTime', qualityStartTime)
            this.$set(this.form.quality, 'qualityEndTime', qualityEndTime)
            this.$set(this.form.quality, 'qualityStatus', qualityStatus)
          }
          this.qualityId = res.result.id
        }).catch(err => {})
      }else if(this.isFromEvent || this.isCopyTask || this.isPlanTaskEdit || this.isPlanTaskCopy || this.isFromProduct || this.isFromPlan) {
        this.getProductQuality()
      }
    },
    getProductQuality() {
      let productArr = this.form?.product || []
      if(isEmpty(this.qualityField) || productArr.length <= 0) return
      
      let productIdList = productArr.map(element => element.id)
      let params = {
        productIdList,
        tenantId: ''
      }
      TaskApi.productQuality(params).then(res => {
        if(productArr.length == 1) {
          this.$set(this.form, 'quality', res.result[0])
          const {qualityStartTime, qualityEndTime, qualityStatus} = res.result[0]
          // 质保状态根据 质保开始时间和结束时间取值
          if ((qualityStartTime || qualityEndTime) && qualityStatus) {
            this.$set(this.form.quality, 'qualityStatus', qualityStatus)
          } else {
            let qualityStatusDefault = this.qualityField?.setting?.defaultQuality
            this.$set(this.form.quality, 'qualityStatus', qualityStatusDefault)
          }
          return
        }
        const arr = []
        res.result.forEach(item => {
          productArr.forEach(element => {
            if(item.id == element.id) {
              arr.push({...item, ...element}) 
            }
          })
        })
        this.$set(this.form, 'product', arr)
        // 计划任务，华大基因灰度可以选择多个产品，不做校验
        const isBgiSaasPlanTask = this.isBgiSaas && this.isPlanTaskPage
        if(productArr.length >= 2 && !isBgiSaasPlanTask) {
          this.QualitySubtext = ONLY_SELECT_ONE_QUALITY
          this.DialogVisible = true
        }
      }).catch(err => {})
    },
    async buildParams() {
      let formValue = disposeFormSubmitTime(this.fields, this.form) // 处理国际化时间转换
      let task = util.packToTask(this.fields, formValue)
      task = this.globalFormSubmissionDataProcessingHandler(this.fields, task);
      
      task.templateId = taskTemplate.value
      task.templateName = taskTemplate.text
      
      if (this.isTaskCreate) {
        formValue.templateId = taskTemplate.value
        formValue.templateName = taskTemplate.text
      }
      
      if (this.allotTask.id) {
        task.id = this.allotTask.id
      }

      if (this.showSparepartServiceList) {
        task.baseTaskInventories = this.buildSparepartParams();
        task.baseTaskFaultLibrary = this.buildFaultLibraryParams();
      }
      task.cardForms = this.buildCardFormsParams();

      const { address, customer, tick, linkman } = task
      let params = {
        address,
        customer,
        eventId: this.isFromEvent ? this.eventId : '',
        flow: this.isFromEvent ? this.urlParams.flow : '',
        linkman,
        task,
        tick
      }
      // 新建工单默认重复报修字段
      if (this.isTaskCreate && this.hasRepeatRepair) {
        params.task.attribute['isRepeatRepair'] = i18n.t('common.base.no')
      }
      let qualityField = this.fields.filter(field => field.formType == 'quality')[0] || {}
      if(!isEmpty(qualityField)) {
        qualityField = this.isTaskCreate ? {...qualityField, id: 0 } : {...qualityField, id: this.qualityId || 0}
        let quality = {...task.quality, ...qualityField, ...this.approveForm}
        params.quality = quality
      }
      return params
    },
    /** 
     * 关闭并打开新的Tab
    */
    closeAndOpenTab(type, keyId) {
      
      try {
        
        const isInFrame = this.validateCurrentWindowIsInFrame()
        
        if (isInFrame) {
          this.postCloseDialogMessage()
          return
        }
        
      } catch (error) {
        console.error(error)
      }
      
      // location.href = url;
      let id = window.frameElement.dataset.id;
      this.$platform.closeTab(id);
    
      let fromId = window.frameElement.getAttribute('id');

      // fix:20171，复制工单时返回工单详情后，会导致fromId为当前页面的id，在执行refreshFromTab时就会把指派弹窗的方法给cancel掉
      // 所以复制工单时优先取fromid
      if (this.isCopyTask) {
        fromId = window?.frameElement?.getAttribute('fromid') || fromId
      }

      let typeObj = {
        'taskView': PageRoutesTypeEnum.PageTaskView,
        'eventView': PageRoutesTypeEnum.PageEventView,
        'planTask': PageRoutesTypeEnum.PageTaskPlanTaskList,
        'taskList': PageRoutesTypeEnum.PageTaskList,
      }
      
      const routeData = {
        type: typeObj[type],
        key: keyId,
        reload: true,
        fromId
      }
      if(this.isCopyTask) {
        routeData.params = 'createType=copyTask';
      }
      openAccurateTab(routeData);
    },
    /** 
     * @description 呼叫中心与工单数据的处理 linkman/address/customer
    */
    callCenterWithTaskDataHandler() {
      let callCenterMap = this.initData?.callCenterMap || {};
      let { callRecordId } = callCenterMap;
      if(!callRecordId) {
        return console.warn(`Caused: current is not have callRecordId, The value is ${callRecordId}`);
      }
      
      // 联系人 地址
      let { linkman, address } = callCenterMap;
      // 更新联系人/客户数据
      if (linkman) {
        let { customer } = linkman;
        this.$set(this.form, TaskFieldNameMappingEnum.Customer, [customerSelectConversion(customer)]);
        this.$set(this.form, TaskFieldNameMappingEnum.Linkman, [linkmanSelectConversion(linkman)]);
      }
      // 更新地址数据
      if(address) {
        this.$set(this.form, TaskFieldNameMappingEnum.Address, [customerAddressSelectConversion(address)]);
      }
    },
    /** 
     * @description 暂存工单方法
    */
    temporarySaveTaskMethod(params, isAllot) {
      this.togglePending(true)
      TaskApi.temporarySaveTask(params).then(res => {
        const isSucc = res.success || res.succ

        platform.notification({
          type: isSucc ? 'success' : 'error',
          title: isSucc ? i18n.t('common.base.messageStatus.success') : i18n.t('common.base.messageStatus.fail'),
          message: !isSucc && res.message
        })

        if (isSucc) {
          this.closeAndOpenTab('taskList')
        }
        if (!isAllot) {
          // 清除连接器缓存
          this.removeConnectorCreateSessionData()
        }
        
        this.togglePending()
      }).catch(err => {
        this.togglePending();
        console.error('temporarySaveTaskMethod error:', err)
      })
    },
    /** 
     * @description 创建工单方法
    */
    async createTaskMethod(params, isAllot, type) {
      if(query.callRecordId) {
        params.callRecordId = query.callRecordId
      }
      if(query.conversationNo) {
        params.conversationNo = query.conversationNo
      } 
      
      // 新增业务类型和业务ID
      if (query.bizType) {
        params.bizType = query.bizType
      }
      if (query.bizId) {
        params.bizId = query.bizId
      }
      
      try {
        this.setConnectorParamsForSubmit(params)
      } catch (error) {
        console.error(error)
      }

      // 暂存工单
      if (type == 'draft') return this.temporarySaveTaskMethod(params, isAllot)

      // 判断是否是从草稿保存为工单
      if (this.workTask.isDelete == 5) {
        params.taskDraft = true
        params.task.templateId = this.workTask.templateId;
        params.task.templateName = this.workTask.templateName;
      }

      // 先判断是否需要高级审批
      let approveParams = {
        action: 'create',
        createInfo: {
          ...params
        }
      }


      // 项目管理参数特殊处理
      let allVipParams = approveParams
      if (this.isFromProject && (this.isProjectTaskDraft || this.isProjectTaskAdd)) {
        allVipParams = this.projectTaskParamsFun(approveParams)
        allVipParams.createInfo.projectTask = allVipParams?.projectTask || {}
        delete allVipParams.projectTask
      }

      this.pending = true;
      const vipApproveResult = await TaskApi.checkNeedVipApprove(allVipParams);
      this.togglePending();
      if (vipApproveResult.success && vipApproveResult.result.needVipApprove) {
        this.createNeedApprove = true
        this.taskId = vipApproveResult.result.params.taskId
        return this.proposeApprove(vipApproveResult.result);
      }

      // 项目管理参数特殊处理
      let commonParams = params
      if (this.isFromProject && (this.isProjectTaskDraft || this.isProjectTaskAdd)) {
        commonParams = this.projectTaskParamsFun(params)
      }
      // 再判断新建是否需要审批
      this.pending = true;
      const approveResult = await TaskApi.createApproveCheck(commonParams);
      this.togglePending();
      if(approveResult.success) {
        if (approveResult.result && approveResult.result.needApprove) {
          this.createNeedApprove = true
          this.taskId = approveResult.result.taskId
          return this.proposeApprove(approveResult.result);
        }
      } else {
        return this.$platform.alert(approveResult.message)
      }

      // 如果是项目管理新建任务过来的 或者是草稿提交过来
      if (this.isFromProject) {
        params = this.projectTaskParamsFun(params)
      }
      
      this.togglePending(true)
      const CreateTaskPromise = query.callRecordId ? TaskApi.createTask4CallCenter(params) : TaskApi.createTask(params)
      
      this.checkNumExceedLimitAfterHandler(CreateTaskPromise)
        .then(res => {
          let isSucc = res.success || res.succ;
          
          platform.notification({
            type: isSucc ? 'success' : 'error',
            title: i18n.t('task.tip.editTip1', {action: i18n.t('task.record.create'), state: isSucc ? i18n.t('common.base.success') : i18n.t('common.base.fail')}),
            message: !isSucc && res.message
          })
          
          if (!isSucc) {
            --this.submitCount
            return this.togglePending();
          }
          
          ++this.submitCount
          
          // 根据是否派单决定跳转地址
          let taskId = query.callRecordId ? res.data.taskId : res.result;
          
          if (isAllot) {
            
            this.refreshFromTab(isAllot)
            
            this.openAllotModel({ 
              createAndAllot: true, // 保存并派单
              ...params.task, 
              id: taskId,
              createUser: this.initData.loginUser || {},
              excutor: {}
            })
            
          } 
          else {
            // 清除连接器缓存
            this.removeConnectorCreateSessionData()
            this.refreshFromTab()
            this.closeAndOpenTab('taskView', taskId)
          }
          this.togglePending()
          
        })
        .catch(err => {
          this.togglePending();
          console.error('err', err)
        })
    },

    projectTaskParamsFun(params) {
      let allParams = {}
      //  带入任务表单固定字段的数据
      let projectTaskParams = JSON.parse(localStorage.getItem('projectTaskCreate'))
      // 新建工单类型的 任务表单弹窗的字段，直接放到新建工单接口

      if (this.isProjectTaskDraft) {
        // 暂存状态只传任务id
        allParams = {
          ...params,
          projectTask: {
            projectId: this.$route.query?.projectId || '',
            id: projectTaskParams.id
          }
        }
      } else {
        allParams = {
          ...params,
          projectTask: {
            projectId: this.$route.query?.projectId || '',
            ...projectTaskParams
          }
        }
      }
      return allParams
    },


    /** 
     * @description 检查版本数量限制
    */
    checkNumExceedLimitHandler() {
      if (!this.checkNumExceedLimitBeforeHandler) return

      // 检测新建计划任务
      if (this.isFromPlan) {
        return (
          this.checkNumExceedLimitBeforeHandler(
            TenantDataLimitSourceEnum.PlanTask,
            TenantDataLimitTypeEnum.PlanTask
          )
        )
      }

      // 检测新建工单
      if (this.isTaskCreate || this.isFromProduct || this.isFromEvent || this.isFromCustomer) {
        return (
          this.checkNumExceedLimitBeforeHandler(
            TenantDataLimitSourceEnum.Task,
            TenantDataLimitTypeEnum.Task
          )
        )
      }
    },
    /**
     * @description 从客户新建工单处理
    */
    customerCreateTaskHandler() {
      if(!this.isFromCustomer && !this.isFromPlan) return
      
      let form = this.$refs.form;
      if(!form) return;
      
      form.updateCustomer(this.form.customer, { isForceUpdateCustomer: true });
      form.relationFieldSelectHandler(TaskFieldNameMappingEnum.Product);
    },
    /** 
     * @description 获取工单类型id
     * 1. 优先取 defaultType 的 id
     * 2. task 数据里的 templateId
     * 3. 工单类型列表中的第一个
     */
    genTemplateId() {
      let defaultType = this.initData?.defaultType || {};
      let workTask = this.workTask || {};
      let firstType = this.types?.[0] || {};
      
      return defaultType.id || workTask.templateId || firstType.id;
    },
    /** 
     * @description 返回
    */
    goBack() {
      
      // 清除连接器缓存
      this.removeConnectorCreateSessionData()
      
      try {
        
        const isInFrame = this.validateCurrentWindowIsInFrame()
        
        if (isInFrame) {
          this.postCloseDialogMessage()
          return
        }
        
      } catch (error) {
        console.error(error)
      }
      
      // 复制工单
      if(this.isCopyTask) {
        let { taskId = '' } = this.urlParams;
        this.pending = true;
        return this.closeAndOpenTab('taskView', taskId)
      }
      // 事件转工单
      else if(this.isFromEvent) {
        let { eventId = '' } = this.urlParams;
        this.pending = true;
        return this.closeAndOpenTab('eventView', eventId);
      }
      // 工单新建
      else if (this.isTaskCreate) {
        let id = window.frameElement.dataset.id;
        
        return this.$platform.closeTab(id)
      }
      
      parent.frameHistoryBack(window)
      
    },
    /** 
     * @description 查询工单配置
     */
    fetchTaskConfig() {
      return TaskApi.getTaskConfig().catch(err => console.warn(err));
    },
    /** 
     * @description 初始化
    */
    initialize() {
      this.initUrl();
      this.initTitle();
      if (this.workTask.isDelete == 5) {
        this.fetchSparepartServiceConfig(this.task.templateId)
      }
    },
    /** 
     * @description 初始化url
    */
    initUrl() {
      let url = '';
      let createUrl = query.callRecordId ? '/task/create4CallCenter' : '/task/create';
      let updateAndEditUrl = '/task/update';
      
      if(this.isTaskEdit) {
        url = this.isFromEvent ? createUrl : updateAndEditUrl;
      } else {
        url = createUrl;
      }
      
      this.submitModel.url = url;
    },
    /** 
     * @description 初始化标题
    */
    initTitle() {
      let title = '';
      
      if(this.isPlanTaskEdit) {
        title = i18n.t('task.edit.editPlan');
      } else if(this.isPlanTaskCopy) {
        title = i18n.t('task.edit.copyPlan');
      } else if(this.isFromPlan) {
        title = i18n.t('task.edit.createPlan');
      } else if((!this.isFromEvent && this.isTaskEdit) || this.workTask.isDelete == 5) {
        title = i18n.t('task.editTask');
      } else {
        title = i18n.t('task.createTask');
      }

      this.pageTitle = title

      if(this.workTask.id){
        this.formEditingMode = 'edit'
      }else{
        this.formEditingMode = 'create'
      }
      
      if (window.frameElement) {
        const currentTabId = window.frameElement.dataset.id;
        platform.setTabTitle({
          id: currentTabId,
          title
        })
      }
    },
    jumpWithPlanTask() {
      try {
        let isFromId = window?.frameElement?.getAttribute('fromid');
        
        if(isFromId) {
          let closeId = window.frameElement.dataset.id;
          this.$platform.refreshTab(isFromId);
          this.$platform.closeTab(closeId);
        } else {
          this.closeAndOpenTab('planTask')
        }
        
      } catch (error) {
        console.warn('jumpWithPlanTask -> error', error)
      }
    },
    /**
     * @description 打开计划任务详情
    */
    jumpWithPlanTaskDetail(planTaskId) {
      try {
        if (!planTaskId) return

        const closeId = window.frameElement.dataset.id
        const fromId = window.frameElement.getAttribute('id')

        this.$platform.closeTab(closeId)
        
        openAccurateTab({
          type: PageRoutesTypeEnum.PagePlanTaskView,
          key: planTaskId,
          params:`id=${planTaskId}`,
          fromId
        })
      } catch (error) {
        console.warn('jumpWithPlanTaskDetail -> error', error)
      }
    },
    refreshFromTab(isAllot) {
      
      let isFromId = window?.frameElement?.getAttribute('fromid');
      let id = window?.frameElement?.getAttribute('id');
      // fix: 21134，华大基因，事件转工单时，保存并派单没有打开派单弹窗(可能是fromid为当前frameid，事件转工单时不刷新fromTab)
      // fix: 24612，偶现保存并派单时会刷新当前页面，fromid等于frame_tab_createTask时不刷新
      // fix: 30137，钉钉端南京小牛智能科技有限公司偶现保存并派单没有打开派单弹窗
      if (isAllot && (isFromId == 'frame_tab_createTask' || this.isFromEvent || isFromId == id)) return;
      if(isFromId) {
        this.$platform.refreshTab(isFromId);
      }
      
    },
    // 打开新建工单弹窗
    async openAllotModel(task = {}) {
      this.allotTask = task
      let createEditTask = {}
      const taskInfo = await this.buildParams()
      createEditTask = {
        createAndAllot: task.createAndAllot, // 保存并派单
        serviceProviderId:this.initData?.serviceProviderId ?? null,
        isCreateEditTask:true,
        task:taskInfo.task ?? null
      }
      this.allotTask.state = TaskStateEnum.CREATED.value
      this.$nextTick(() => {
        this.$refs.TaskAllotModal && this.$refs.TaskAllotModal.outsideShow(createEditTask)
      })
      this.togglePending()
      this.backParams.task.id = task.id
    },
    isEditTime() {
      let isEditTime = true
      if(this.isCalendar) {
        let planStartTime = this.form?.[TaskFieldNameMappingEnum.PlanStartTime]
        let planEndTime = this.form?.[TaskFieldNameMappingEnum.PlanEndTime]
        if(!planStartTime && !planEndTime) isEditTime = false
      }else {
        let planTime = this.form?.[TaskFieldNameMappingEnum.PlanTime]
        if(!planTime) isEditTime = false
      }
      return isEditTime
    },
    /** 
     * @description 新建计划任务弹窗
    */
    async planTaskCreateDialogOpen() {
      let flag = this.qualityValidate()
      let { isQualityDialog, isAllowQualityIn } = this.$refs.form
      if(isQualityDialog || isAllowQualityIn || flag) return
      if(!this.isEditTime()) return this.$platform.alert(PLATN_TASK_PLAN_TIME_REQUIRES_MESSAGE)
      
      this.submitting = true;
      
      this.$refs.form
        .validate()
        .then(async (valid) => {
          this.submitting = false;
          
          if (!valid) return Promise.reject('validate fail.');
          
          // 获取工单配置
          let result = await this.fetchTaskConfig();
          let taskConfig = result?.taskConfig || {};
          this.$set(this, 'taskConfig', taskConfig);
          
          // 显示计划任务弹窗
          let planTaskEditFormEl = this.planTaskEditFormEl;
          if(planTaskEditFormEl) {
            // 复制计划任务
            if(this.isPlanTaskCopy) {
              let planTask = this.initData?.planTask || {};
              planTaskEditFormEl.toggle(true, planTask);
            } else {
              planTaskEditFormEl.toggle(true, { endSetting: { endBy: 'date', value: this.deadlineTime  }, advance: 1});
              planTaskEditFormEl.fetchExeinsyn(this.form?.customer?.[0]?.id);
            }
            
          }
          
          this.submitting = false;
        })
    },
    /** 
     * @description 编辑计划任务弹窗
    */
    async planTaskEditDialogOpen() {
      let flag = this.qualityValidate()
      let { isQualityDialog, isAllowQualityIn } = this.$refs.form
      if(isQualityDialog || isAllowQualityIn || flag) return
      if(!this.isEditTime()) return this.$platform.alert(PLATN_TASK_PLAN_TIME_REQUIRES_MESSAGE)
      
      this.submitting = true;
      
      this.$refs.form
        .validate()
        .then(async (valid) => {
          this.submitting = false;
          
          if (!valid) return Promise.reject('validate fail.');
          
          // 获取工单配置
          let result = await this.fetchTaskConfig();
          let taskConfig = result?.taskConfig || {};
          this.$set(this, 'taskConfig', taskConfig);
          
          // 显示计划任务弹窗
          let planTaskEditFormEl = this.planTaskEditFormEl;
          let planTask = this.initData?.planTask || {};
          planTaskEditFormEl && planTaskEditFormEl.toggle(true, planTask);
          
          this.submitting = false;
        })
    },
    /** 
     * @description 新建计划任务提交
    */
    planTaskCreateSubmit(params = {}) {
      const PlanTaskCreatePromise = TaskApi.createPlanTask(params)

      this.checkNumExceedLimitAfterHandler(PlanTaskCreatePromise)
        .then(res => {
          let isSucc = res.success
          
          platform.notification({
            type: isSucc ? 'success' : 'error',
            title: i18n.t('task.tip.editPlanTip1', {action: i18n.t('task.record.create'), state: isSucc ? i18n.t('common.base.success') : i18n.t('common.base.fail')}),
            message: !isSucc && res.message
          })
          
          if (!isSucc) {
            return this.togglePending();
          }

          if(this.isPlanTaskCopy) { // 复制计划任务跳转详情
            this.refreshFromTab()
            this.jumpWithPlanTaskDetail(res.result);
          } else {
            this.jumpWithPlanTask();
          }

          this.togglePending();
          
        })
        .catch(err => console.error('err', err))
        .finally(() => {
          // 计划任务元素
          let planTaskEditFormEl = this.planTaskEditFormEl;
          planTaskEditFormEl && planTaskEditFormEl.togglePending();
          
          this.togglePending();
        })
    },
    /** 
     * @description 编辑计划任务提交
    */
    planTaskEditSubmit(params = {}) {
      TaskApi.editPlanTask(params)
        .then(res => {
          let isSucc = res.success;
          
          platform.notification({
            type: isSucc ? 'success' : 'error',
            title: i18n.t('task.tip.editPlanTip1', {action: i18n.t('common.base.edit'), state: isSucc ? i18n.t('common.base.success') : i18n.t('common.base.fail')}),
            message: !isSucc && res.message
          })
          
          if (!isSucc) {
            return this.togglePending();
          }
          
          this.jumpWithPlanTask();
          this.togglePending();
          
        })
        .catch(err => console.error('err', err))
        .finally(() => {
          // 计划任务元素
          let planTaskEditFormEl = this.planTaskEditFormEl;
          planTaskEditFormEl && planTaskEditFormEl.togglePending();
          this.togglePending();
        })
    },
    /** 
     * @description 从产品新建工单处理
    */
    productCreateTaskHandler() {
      if(!this.isFromProduct && !this.isFromPlan) return
      
      let form = this.$refs.form;
      if(!form) return;
      
      // 更新产品数据
      form.updateProduct(
        this.form.product,
        {isFromProduct:true, isForceUpdateCustomer: true, isUpdateCustomerProduct: false, isSilentUpdateLinkmanAndAddress: true }
      );
    },
    /** 
     * @description 刷新tab
    */
    reloadTab() {
      let fromId = window.frameElement.getAttribute('fromid');
      
      this.$platform.refreshTab(fromId);
    },
    /** 
     * @description 关联显示项
    */
    relationFieldHandler() {
      // 子组件form
      this.$nextTick(() => {
        let form = this.$refs.form;
        if(!form) return;
        
        // 关联显示项选择
        form.relationFieldSelectHandler(TaskFieldNameMappingEnum.Customer);
        form.relationFieldSelectHandler(TaskFieldNameMappingEnum.Product);

        // bug: 22654 事件转工单未显示客户关联工单/归档工单数量
        if(this.isFromEvent)  {
          const selectedCustomerId = this.form?.customer?.[0]?.value;
          // 查询关联工单数量
          form.fetchCountForCreate({ module: TaskFieldNameMappingEnum.Customer, id: selectedCustomerId });
          // 获取归档工单数量
          form.getArchiveCount(selectedCustomerId, 'customer').then(res => {
            form.customerArchiveCount = res || 0
          });
        }
      })
      
    },
    onApproveSuccessHandler(value) {
      this.approveForm = value
      this.submitSuccess(false)
    },
    // 展示审批弹窗
    showApprove(data) {
      this.$refs.proposeApprove.openDialog(data)
    },
    onApproveClosedHandler(data) {
      // 1.如果新建工单需要审批/高级审批，审批弹窗取消后跳转工单详情
      // 2.新建工单发起审批成功，跳转工单详情
      if ((this.createNeedApprove && this.workTask.isDelete != 5) || (data?.isSuccess)) {
        const taskId = this.task.id || this.taskId
        this.closeAndOpenTab('taskView', taskId)
      }
    },
    // 新建发起审批
    proposeApprove(data) {
      this.$refs.proposeApprove2.openDialog(data, () => {})
    },
    // 提交逻辑复用
    submitSuccess(isAllot) {
      this.submitting = true;
      
      this.$refs.form
        .validate()
        .then(async valid => {
          scrollIntoFirstRequireDom(this.$refs.form.$refs.form)
          this.submitting = false
          if (!valid) return Promise.reject('validate fail.')
          document.getElementById('task-edit-view-copy').style.display = 'none'
          const params = await this.buildParams()
          // 校验计划开始时间和计划完成时间（1。计划开始时间或者计划完成时间不能早于现在 2.计划开始不能大于计划完成）
          if(params.task){
            let startTime = params.task?.planStartTime ? parseDateTime(params.task.planStartTime).getTime() : '';
            let endTime = params.task?.planEndTime ? parseDateTime(params.task.planEndTime).getTime() : '';
            let nowTime = safeNewDate().getTime();
            let planTimeTip = ''
            if(!this.isTaskEdit && startTime && startTime < nowTime){
              planTimeTip = PLAN_START_TIME_NOT_LESS_THEN_NOW_MEESSAGE
            } else if(!this.isTaskEdit && endTime && endTime < nowTime) {
              planTimeTip = PLAN_END_TIME_NOT_LESS_THEN_NOW_MEESSAGE
            } else if(startTime && endTime && startTime > endTime) {
              planTimeTip = i18n.t('task.tip.planTimeTip5');
            }

            if(planTimeTip) {
              platform.notification({
                type: 'error',
                title: planTimeTip
              })
              return Promise.reject(i18n.t('task.tip.planTimeTip2'));
            }
          }
          this.togglePending(true)
          
          // 指派需要对比 现在的表单于上一次表单数据是否相同，不相同则更新工单数据
          // 是否是相同的工单数据
          let isSameForm = true
          try {
            isSameForm = (
              JSON.stringify(params) === JSON.stringify(this.backParams)
              && Object.keys(this.backParams).length > 0
            )
          } catch (error) {
            isSameForm = true
          }

          if (this.isTaskEdit && params.task && Array.isArray(params.task.attachment)) {
            // fix: 后端会查询回执附件拼接上去，所以前端需要过滤下回执附件
            params.task.attachment = params.task.attachment.filter(item => !item.receipt);
          }

          // 创建之前绑定客户和产品
          let isUnbind = params.task?.products.filter(item=>!item.customerId).length // 判断是否有未关联的，需要提示
          if(this.productCreateUnBindCustomer && isUnbind){
            let nameArr = [], productIds = []
            params.task.products.filter(item=>!item.customerId).forEach(item=>{
              nameArr.push(item.name)
            })
            this.$confirm(i18n.t('common.base.tip.productBindCustomerTip', {productName: nameArr.join(','), name: i18n.t('common.base.task')}), i18n.t('common.base.toast'), {
              confirmButtonText: i18n.t('common.base.makeSure'),
              cancelButtonText: i18n.t('common.base.cancel'),
              type: 'warning',
            }).then(()=>{
              if(params.task && params.task.products.length){
                params.task.products.forEach(item=>{
                  productIds.push(item.id)
                })
              }
              let bindParams = {
                productIds,
                customerId:params.customer?.id ? params.customer?.id : null,
                linkman:{
                  id:params.linkman?.id ? params.linkman.id : null
                },
                address:{
                  id:params.address?.id ? params.address.id : null
                }
              }
              bindCustomer(bindParams).then(bindRes=>{
                if(!bindRes.success) return false
                // 绑定成功产品里面插入客户id
                params.task.products.forEach(item=>{
                  item.customerId = params.task.customer.id
                })
                this.togglePending(true)
                // 表单数据不相同 或非指派
                if (!isSameForm || !isAllot) {
                  this.backParams = params
                  let isFirstCreate = this.submitCount <= 0 && this.isTaskCreate
                  let taskMethodFunc = isFirstCreate ? this.createTaskMethod : this.updateTaskMethod
                  return taskMethodFunc(params, isAllot)
                }
    
                this.submitCount > 0 ? this.openAllotModel(this.allotTask) : this.createTaskMethod(params, isAllot)
              })
            }).catch((err)=>{
              this.togglePending()
              console.error(err)
            })
          }else{
            this.togglePending(true)

            // 表单数据不相同 或非指派
            if (!isSameForm || !isAllot) {
              this.backParams = params
              let isFirstCreate = this.submitCount <= 0 && this.isTaskCreate
              let taskMethodFunc = isFirstCreate ? this.createTaskMethod : this.updateTaskMethod
              return taskMethodFunc(params, isAllot)
            }

            this.submitCount > 0 ? this.openAllotModel(this.allotTask) : this.createTaskMethod(params, isAllot)
          }
        })
        .catch(err => {
          this.togglePending();
          console.error(err);
        })
    },

    /** 
     * @description 提交
     * @param {Boolean} isAllot 是否派单
    */
    qualityValidate() {
      let flag = false
      let productLength = this.form?.product?.length || 0
      if(!isEmpty(this.qualityField)) {
        if(productLength <= 0) {
          this.QualitySubtext = i18n.t('task.tip.qualityTip1')
          this.DialogVisible = true
          flag = true
        }else if(productLength >= 2){
          // 计划任务，华大基因灰度可以选择多个产品，不做校验
          const isBgiSaasPlanTask = this.isBgiSaas && this.isPlanTaskPage
          if (!isBgiSaasPlanTask) {
            flag = true
            this.$refs.form.isQualityDialog = true
          }
        }
      }
      let { isQualityDialog, isAllowQualityIn } = this.$refs.form
      flag = isQualityDialog || isAllowQualityIn || flag
      return flag
    },
    submit: _.debounce(async function (isAllot = false, type) {
      // 暂存时不做校验
      if (type == 'draft') {
        const params = await this.buildParams()
        return this.isTaskCreate ? this.createTaskMethod(params, isAllot, 'draft'): this.temporarySaveTaskMethod(params, isAllot)
      }
      let flag = this.qualityValidate()
      // 故障库只允许选择一个产品
      const isFaultLibraryDialog = this.$refs.form.isFaultLibraryDialog
      // let { isQualityDialog, isAllowQualityIn } = this.$refs.form
      if(this.submitting || flag || isFaultLibraryDialog) return
      const valid = await this.$refs.form.validate()
      scrollIntoFirstRequireDom(this.$refs.form.$refs.form)
      if (!valid) return Promise.reject('validate fail.')
      // 判断是否需要审批，新建的时候不需要调用后端接口判断是否需要审批，编辑时需要根据设置字段加接口判断
      if(this.qualityField?.setting?.allowProduct == 2 && this.form?.quality?.qualityStatus == 'OUT') {
        let data = this.qualityField.setting
        if(this.isTaskCreate) {
          this.showApprove(data)
        }else {
          // 编辑的时候看产品是否有变动，如果有变动则直接发起审批，没有变动的话则需要调用接口判断，因为会有撤回审批和审批通过再编辑的情况
          if (this.productId == this.form.product[0].id) {
            TaskApi.checkQualityApprove({ taskId: this.task.id }).then(res => {
              if (!(res.result)) {
                this.showApprove(data)
              }else {
                this.submitSuccess(isAllot)
              }
            }).catch(err => {})
          }else{
            this.showApprove(data)
          }
        }
        return
      }
      this.submitSuccess(isAllot)
      
    }, 250),

    // 获取新建工单表单提交参数 用于新建日程工单调用
    async getPostParams(isAllot = false){
      try {
        const valid = await this.$refs.form.validate()
        if (!valid) return Promise.reject('validate fail.')
        const params = await this.buildParams()

        if (this.isTaskEdit && params.task && Array.isArray(params.task.attachment)) {
          // fix: 后端会查询回执附件拼接上去，所以前端需要过滤下回执附件
          params.task.attachment = params.task.attachment.filter(item => !item.receipt);
        }

        // 新建工单默认重复报修字段
        if (this.isTaskCreate && this.hasRepeatRepair) {
          params.task.attribute['isRepeatRepair'] = i18n.t('common.base.no')
        }
        
        return params
      } catch (error) {
        console.error(error);
      }
    },
    
    /** 
     * @description 计划任务提交
    */
    submitWithPlanTask: _.debounce(function (planTaskParams = {}) {
      if (this.pending) {
        return console.warn('Caused: can not submitWithPlanTask action, because this.pending is true');
      }
      
      this.togglePending(true);
      // 计划任务元素
      let planTaskEditFormEl = this.$refs.planTaskEditForm;
      planTaskEditFormEl && planTaskEditFormEl.togglePending(true);
      
      let task = util.packToTask(this.fields, this.form);
      
      task = this.globalFormSubmissionDataProcessingHandler(this.fields, task);
      
      task.templateId = taskTemplate.value;
      task.templateName = taskTemplate.text;
      
      const params = {
        ...planTaskParams,
        task
      };
      // 从合同详情跳进来时，会传入合同id，需要传给后端
      if(this.contractId){
        params.contractId = this.contractId
      }
      
      if (this.isFromPlan) {
        this.$track.clickStat(this.$track.formatParams('CREATE_PLAN_TASK_SUCCESS'));
        return this.planTaskCreateSubmit(params);
      }
      if (this.isPlanTaskEdit) {
        this.$track.clickStat(this.$track.formatParams('EDIT_PLAN_TASK_SUCCESS'));
        return this.planTaskEditSubmit(params);
      }
      if(this.isPlanTaskCopy) {
        // 复制计划任务
        return this.planTaskCreateSubmit(params);
      }
      
    }, 250),
    togglePending(pending = false) {
      this.pending = pending;
      this.loadingPage = pending;
    },
    justTogglePending(pending = false) {
      this.pending = pending;
    },
    /** 
     * @description 编辑工单方法
    */
    updateTaskMethod(params, isAllot = false) {
      if(this.needServerDeleFiles.length){
        params.deleteFiles = this.needServerDeleFiles
      }
      TaskApi.editTask(params)
        .then(res => {
          let isSucc = res.success;
          platform.notification({
            type: isSucc ? 'success' : 'error',
            title: i18n.t('task.tip.editTip1', {action: i18n.t('common.base.update'), state: isSucc ? i18n.t('common.base.success') : i18n.t('common.base.fail')}),
            message: !isSucc && res.message
          })
          
          if (!isSucc) {
            --this.submitCount
            return this.togglePending();
          }
          ++this.submitCount
          
          // 根据是否派单决定跳转地址
          let taskId = this.editId || this.allotTask.id;
          
          if (isAllot) {
            
            this.refreshFromTab(isAllot)
            
            this.openAllotModel({ 
              ...params.task, 
              templateId: this.task.templateId, 
              id: taskId,
              createUser: this.task.createUser,
              excutor: this.task.excutor
            })
          } else {
            
            this.refreshFromTab()
            
            if(query.agendaTask) {
              // 刷新日历
              let closeId = window.frameElement.dataset.id;
              this.$platform.closeTab(closeId);
              this.reloadTab()
            }
            else {
              this.closeAndOpenTab('taskView', taskId)
            }
          }
          
          this.togglePending()
          
        })
        .catch(err => {
          this.togglePending();
          console.error('err', err);
        })
    },
    // 跳转到项目详情
    goProject() {
      let closeId = window.frameElement.dataset.id;
      this.$platform.closeTab(closeId);
      this.reloadTab()
      const fromId = window.frameElement.getAttribute('id')
      // 编辑的工单类型的任务的话，就直接返回到之前的页面
      const { templateId, projectId } = this.$route.query
      // this.refreshFromTab()
      openAccurateTab({
        type: PageRoutesTypeEnum.PageProjectManageView,
        params: `templateId=${templateId}&id=${projectId}`,
        reload: true,
        fromId,
      });
    },
    /** 
     * @description 更新工单类型
    */
    updateTaskTemplateId(template = {}) {
      taskTemplate = template || {};
      this.template = template
    },
    /** 
     * @description 查询工单类型备件清单配置
    */
    fetchSparepartServiceConfig(templateId) {
      if (!templateId) {
        return console.warn('Caused: [SparepartSeviceList] templateId is empty')
      }

      TaskApi.getConfigByTaskTypeId({ templateId })
        .then(res => {
          if (res.success) {
            this.sparepartConfig = res.result || [];

            // 重置备件清单数据
            this.$nextTick(() => {
              if(this.$refs.partServiceList) {
                this.$refs.partServiceList.reset();
              }
            })
          }
        })
        .catch(err => {
          console.error(err)
        })
    },
    /** 
     * @description 查询工单类型附加组件配置
    */
    fetchTaskCardByIds(templateId) {
      try {
        if (!templateId) {
          return console.warn('Caused: [SparepartSeviceList] templateId is empty')
        }
        
        const params = {
          templateId,
          cardIds: this.customCardListFilter.map(x => x.id)
        }

        TaskApi.getTaskCardByIds(params)
          .then(async(res) => {
            const { data, success } = res;

            if (success) {
              this.customCardList = this.customCardListFilter.map(x => {
                x.fields = (data[x.id]?.taskCardFields || []).map(t => {
                  delete t.defaultValue;
                  t.isSystem = 0;
                  return t;
                });
                x.cardId = x.id;
                x.cardName = x.name;

                // TODO 后端草稿状态下canCreate返回为false，先试用init中的
                const initCardInfo = this.initData.cardInfo || [];
                const initCardItem = initCardInfo.find(c => c.cardId === x.id)
                const info = this.task.id ? initCardItem : data[x.id]

                return {
                  ...info,
                  ...x
                };
              })

              const res = await TaskApi.getTaskCardInfoByTaskId({ taskId: this.task.id });
              if(res?.result?.length){
                this.cardForms = res.result || [];
              }else {
                // 初始化附加组件保存数据
                this.cardForms = this.customCardList.map(x => {
                  return {
                    attribute: x.inputType === 'single' ? {} : [],
                    cardId: x.cardId,
                    inputType: x.inputType
                  }
                })
              }
            }
          })
          .catch(err => {
            console.error(err)
          })

      }catch(e) {
        
      }
    },
    /** 
     * @description 拼装备件清单数据
    */
    buildSparepartParams() {
      let { sparepartData = [], serviceData = [], materialData = [], serviceItem, sparepart, materialItem } = this.$refs.partServiceList;
      let customerName = this.form?.customer?.[0]?.label;

      /**
       * IN O 代表保内 ，OUT 1 代表保外
       * 如果工单有质保状态就取质保状态的，如果没有质保状态就默认保外。
       */
      const qualityStatus = this.form?.quality?.qualityStatus || 'OUT'
      const warrantyStatus = qualityStatus === 'IN' ? 0 : 1
      
      let result = [];

      sparepartData.forEach(item => {
        result.push({
          customerName,
          type: 1,
          cardId: sparepart.id,
          relationId: item.id,
          preNum: item.preNum,
          salePrice: item.salePrice || 0,
          salePriceCurrency: item.salePriceCurrency || 'CNY',
          relationName: item.name
        })
      })

      serviceData.forEach(item => {
        result.push({
          customerName,
          type: 2,
          cardId: serviceItem.id,
          relationId: item.id,
          preNum: item.preNum,
          salePrice: item.salePrice || 0,
          salePriceCurrency: item.salePriceCurrency || 'CNY',
          relationName: item.name
        })
      })

      materialData.forEach(item => {
        result.push({
          customerName,
          type: 3,
          cardId: materialItem.id,
          relationId: item.id,
          preNum: item.preNum,
          relationName: item.name,
          warrantyStatus,
          snManage: item.snManage,
          property: item.property,
          unit: item.unit,
          salePrice: item.salePrice || 0,
          salePriceCurrency: item.salePriceCurrency || 'CNY',
          materialSn: item.materialSn
        })
      })
      
      return result;
    },
    // 拼装故障清单内容
    buildFaultLibraryParams() {
      const { faultData = [] } = this.$refs.partServiceList;
      
      return faultData.map(x => {
        return {
          ...x,
          id: '',
        }
      });
    },
    buildCardFormsParams() {
      const arr = [];
      this.cardForms.forEach(x => {
        
        if(x.inputType === 'single') {
          if(x?.attribute?.operateType) delete x.attribute.operateType;

          arr.push(x);
        }else {
          const multipleList = x.attribute.map(v => {
            if(v.operateType) delete v.operateType;

            return {
              ...x,
              attribute: v
            };
          })

          arr.push(...multipleList)
        }
      })

      return arr;
    },
    async getAttachData() {
      try {
        const res = await TaskApi.getTaskCardInfoByTaskId({ taskId: this.task.id });
        this.cardData = res.result || [];
      } catch (error) {
        console.warn('getAttachData -> error', error);
      }
    },
    handlePlantimeFields(){
      // 日程新建工单需要将计划开始时间和结束时间字段调整到表单最前面
      if(this.planStartTime && this.planEndTime) {
        let newFields = []
        const planStartTimeField = this.fields.filter(field=>field.formType === 'planStartTime')
        const planEndTimeField = this.fields.filter(field=>field.formType === 'planEndTime')
        for (let index = 0; index < this.fields.length; index++) {
          const field = this.fields[index];
          if(field.formType != 'planStartTime' && field.formType != 'planEndTime') {
            newFields.push(field)
          }
        }
        this.fields = [...planStartTimeField, ...planEndTimeField, ...newFields]
      } 
    },
    onTaskAllotSuccessHandler() {
      try {
        
        const isInFrame = this.validateCurrentWindowIsInFrame()
        
        if (isInFrame) {
          this.postCloseDialogMessage()
          return
        }
        
      } catch (error) {
        console.error(error)
      }
    },
    /** 
     * @description 事件子表单数据转成工单子表单
    */
    async eventConversionTaskSubForms(form = {}){
      try{
        const params = {
          taskTypeId: this.genTemplateId(),
          eventId: this.eventId
        }
        const {status,data} = await eventConversionTask(params)
        if(status == 0) form.subForms = data
        return form
      }catch(err){
        console.log(err)
        return form
      }
    },
    getDeleteFiles(files){
      this.needServerDeleFiles = [...this.needServerDeleFiles,...files]
    }
  },
  components: {
    [TaskEditForm.name]: TaskEditForm,
    [PlanTaskEditForm.name]: PlanTaskEditForm,
    [PartSeviceList.name]: PartSeviceList,
    [ProposeApproveDialog.name]: ProposeApproveDialog,
    ProposeApproveDialog2,
    TaskAllotModal,
    TaskProcessSteps,
    FormCellChange
  }
}